package com.clp.protocol.modbus_tcp.connect.config;

import com.clp.protocol.core.client.ConnectionAlreadyExistException;
import com.clp.protocol.core.common.Checkable;
import com.clp.protocol.core.utils.IpUtil;
import com.clp.protocol.core.utils.LocalHostDoesNotExistException;
import com.clp.protocol.core.utils.StringUtil;
import com.clp.protocol.modbus_tcp.client.ModbusClient;
import lombok.Getter;

@Getter
public abstract class ConnConfig implements Checkable {
    /**
     * 默认本地ip
     */
    public static final String DEFAULT_LOCAL_HOST = IpUtil.getLocalIpSet().iterator().next();
    /**
     * 默认本地端口号（0表示随机本地端口）
     */
    public static final int DEFAULT_LOCAL_PORT = 0;
    /**
     * 默认远程端口号
     */
    public static final int DEFAULT_REMOTE_PORT = 502;
    /**
     * 默认地址
     */
    public static final int DEFAULT_ADDR = 1;

    /******************************************************************************************************************/

    private final String localHost;
    private final int localPort;
    private final String remoteHost;
    private final int remotePort;
    /**
     * 地址
     */
    protected final int addr;

    protected ConnConfig(Configurer<? extends Configurer<?>> configurer) {
        this.localHost = configurer.localHost;
        this.localPort = configurer.localPort;
        this.remoteHost = configurer.remoteHost;
        this.remotePort = configurer.remotePort;
        this.addr = configurer.addr;
    }

    protected static class Configurer<C extends Configurer<C>> {
        private String localHost = DEFAULT_LOCAL_HOST;
        private int localPort = DEFAULT_LOCAL_PORT;
        private String remoteHost;
        private int remotePort = DEFAULT_REMOTE_PORT;
        protected int addr = DEFAULT_ADDR;

        @SuppressWarnings("unchecked")
        private C self() {
            return (C) this;
        }

        public C connection(String remoteHost, int remotePort) {
            return connection(DEFAULT_LOCAL_HOST, DEFAULT_LOCAL_PORT, remoteHost, remotePort);
        }

        public C connection(String localHost, int localPort, String remoteHost, int remotePort) {
            this.localHost = localHost;
            this.localPort = localPort;
            this.remoteHost = remoteHost;
            this.remotePort = remotePort;
            return self();
        }

        public C addr(int addr) {
            this.addr = addr;
            return self();
        }
    }

    @Override
    public void check() throws Throwable {
        // 检查 ip 是否合法，本地ip是否存在
        if (StringUtil.isBlank(localHost) || StringUtil.isBlank(remoteHost)) {
            throw new RuntimeException("非法的本地IP地址或远程IP地址！");
        }
        if (!IpUtil.hasLocalHost(localHost)) {
            throw new LocalHostDoesNotExistException(localHost);
        }

        // 检查 从站ip 是否已经被使用
        if (ModbusClient.get().hasMaster(remoteHost, remotePort)) {
            throw new ConnectionAlreadyExistException(remoteHost, remotePort);
        }
    }
}
